package org.javaongems.client.vcl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.javaongems.client.rt.awt.Rectangle;
import org.javaongems.client.rt.awt.ScreenRectUtils;

import com.google.gwt.user.client.Event;

public class WinControl extends Control {
	final static public String TABORDER_PROP = "tab-order";
	protected ArrayList controls = new ArrayList();
	protected Rectangle clientRect = new Rectangle();
	protected Control clientChild;
	protected int tabOrder = 0;
	
	public List getControls() {
		return controls;
	}
	
	public void setTabOrder(int idx) {
		if (tabOrder == idx)
			return;
		paintAttributeTabOrder();
	}
	
	public int getTabOrder() {
		return tabOrder;
	}
	
	public void setFocus() {
		if (!isReadyToPaint())
			return;
		domRenderer.setFocus(true);
	}
	
	protected void paintAttributeTabOrder() {
		if (!isReadyToPaint())
			return;
		domRenderer.setTabIndex(tabOrder);
	}
	
	protected void paintChildren() {
		for (Iterator iter = controls.iterator(); iter.hasNext();) {
			Control ctrl = (Control) iter.next();
			ctrl.repaint();
		}
	}
	
	protected void paintChildrenZorder() {
		for (Iterator iter = controls.iterator(); iter.hasNext();) {
			Control ctrl = (Control) iter.next();
			ctrl.paintAttributeZindex();
		}
	}
	
	protected void adopt(Control child) {
		if (!controls.contains(child)) {
			controls.add(child);
			super.adopt(child);
		}
	}
	
	protected void disown(Control child) {
		int pos = controls.indexOf(child);
		if (controls.remove(child)) {
			super.disown(child);
		}
	}
	
	protected Control getClientChild() {
		return clientChild;
	}	
	
	protected void setClientChild(Control child) {
		clientChild = child;
	}
	
	protected void recalcClientRectAndUpdateClientChild() {
		if (isLoading()) 
			return;
		recalcClientRect();
		if (clientChild != null)
			clientChild.setBoundsRect(clientRect);
	}

	protected void recalcClientRect() {
		initialiseClientBounds();
		Rectangle ctrlBnds = new Rectangle();
		for (Iterator iter = controls.iterator(); iter.hasNext();) {
			ctrlBnds.setBounds(clientRect);
			Control ctrl = (Control) iter.next();
			int ctrlAlign = ctrl.getAlign();
			if (ctrlAlign == ALIGN_NONE || ctrlAlign == ALIGN_CLIENT)
				continue;
			int ctrlHght = ctrl.getHeight();
			int ctrlWdth = ctrl.getWidth(); 
			switch (ctrlAlign) {
			case ALIGN_TOP: {
				ScreenRectUtils.reduceAndMove(0, ctrlHght, clientRect);
				ctrlBnds.height = ctrlHght;
				ctrl.setBoundsRect(ctrlBnds);
				break;
			}
			case ALIGN_LEFT: {
				ScreenRectUtils.reduceAndMove(ctrlWdth, 0, clientRect);
				ctrlBnds.width = ctrlWdth;
				ctrl.setBoundsRect(ctrlBnds);
				break;	
			}
			case ALIGN_BOTTOM: { 
				ScreenRectUtils.reduce(0, ctrlHght, clientRect);
				ctrlBnds.height = ctrlHght;
				ctrlBnds.y = clientRect.y + clientRect.height;
				break;
			}
			case ALIGN_RIGHT: {
				ScreenRectUtils.reduce(ctrlWdth, 0, clientRect); 
				ctrlBnds.width = ctrlWdth;
				ctrlBnds.x = clientRect.x + clientRect.width;
				break;
			}
			}
		}
	}

	protected void initialiseClientBounds() {
		clientRect.setBounds(boundsRect);
		clientRect.setLocation(0, 0);
	}
	
	protected int getSinkEvents() {
		int curr = super.getSinkEvents();
		return Event.FOCUSEVENTS | Event.KEYEVENTS | curr;
	}
	
	public int getControlCount() {
		return controls.size();
	}
	
	public void insertComponent(Component child) {
		super.insertComponent(child);
		if (child instanceof Control)
			adopt((Control)child);
	}
	
	public void removeComponent(Component child) {
		super.removeComponent(child);
		if (child instanceof Control) 
			disown((Control)child);
	}
	
	protected boolean onControlEvent() {
		boolean ret = super.onControlEvent();
		if (ret)
			return ret;
		if (!(listener instanceof WinControlListener)) 
			return false;
		WinControlListener lsnr = (WinControlListener) listener;
	    switch (ControlEvent.eventType) {
	      case Event.ONFOCUS: 		lsnr.onEnter(this); break;
	      case Event.ONBLUR: 		lsnr.onExit(this); break;
	      case Event.ONKEYDOWN: 	lsnr.onKeyDown(this, ControlEvent.listenerInfo[ControlEvent.LI_KEY], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT]); break;
	      case Event.ONKEYPRESS: 	lsnr.onKeyPress(this, ControlEvent.listenerInfo[ControlEvent.LI_KEY], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT]); break;
	      case Event.ONKEYUP: 		lsnr.onKeyUp(this, ControlEvent.listenerInfo[ControlEvent.LI_KEY], ControlEvent.listenerInfo[ControlEvent.LI_SHIFT]); break;
		default:
			return false;
		}
	    return true;
	}
	
	protected boolean paintFrame() {
		if (super.paintFrame()) {
			paintAttributeTabOrder();
			return true;
		}
		return false;
	}

	protected void writeProperties(PropertiesWriter wrtr) {
		super.writeProperties(wrtr);
		writeTabOrderProperty(wrtr);
	}
	
	protected void writeTabOrderProperty(PropertiesWriter wrtr) {
		if (tabOrder != 0)
			wrtr.writeNumber(TABORDER_PROP, tabOrder);
	}

	protected void readProperties(PropertiesReader rdr) {
		super.readProperties(rdr);
		setTabOrder((int)rdr.readNumber(TABORDER_PROP, 0));
	}	
}
